package utils;



import org.json.JSONException;
import org.json.JSONObject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.function.Executable;
import org.junit.platform.commons.util.UnrecoverableExceptions;
import org.opentest4j.MultipleFailuresError;


import java.util.*;

public class DataAssert {

    public static JSONObject jsonAssertions = new JSONObject();

    private DataAssert() {

    }

    private static class Inner {
        private static DataAssert dataAssert = new DataAssert();
    }

    public static DataAssert newInstance() {
        return Inner.dataAssert;
    }

    List<List<String>> strings = new LinkedList<>();

    /**
     * 检查jsondata中是否存在key ，检查jsondata中的key的值是否是value
     *
     * @param jsonData json数据
     * @param key      期望比较的键
     * @param value    key对应的值
     * @return 返回当前对象
     */
    public DataAssert collectArguments(String jsonData, String key, String value) {
        ArrayList<String> list = new ArrayList<>();
        list.add(key);
        list.add(value);
        list.add(jsonData);
        strings.add(list);
        return this;
    }

    /**
     * 执行list数组中的断言操作
     * 如果测试用例有多处断言：
     * 1-统一在用例最后的位置搜集断言操作（collectArguments）和执行（retrieveArgument）
     * 2-在用例不同位置调用collectArguments 进行断言，在最后位置执行retrieveArgument
     * 这么操作的原因是retrieveArgument操作如果存在断言失败，后面的代码将不会执行
     */
    public void retrieveArgument() {

        List<Executable> executableList = new ArrayList<>();
        for (List<String> list : strings) {
            String key = list.get(0);
            String value = list.get(1);
            String jsondata = list.get(2);
            GetJsonValue getJsonValue = new GetJsonValue();
            String realValue;

            try {
                realValue = getJsonValue.getValue(jsondata, key);
            } catch (JSONException e) {
                executableList.add(() -> Assertions.fail("jsondata中没找到key：" + key));
                continue;
            }

            String finalRealValue = realValue;
            executableList.add(() -> Assertions
                    .assertEquals(value, finalRealValue, "key：" + key + " 对应的值错误"));
        }
        strings.clear();
        Assertions.assertAll(executableList);
    }

    /**
     * 统一执行多个断言，如果有一次统一抛出到控制台
     */
    public void assertAll(String heading) {
        List<Throwable> failures = new ArrayList<>();

        Iterator<String> it = jsonAssertions.keys();
        while (it.hasNext()) {
            String key = it.next();
            Executable executable = (Executable) jsonAssertions.get(key);
            try {
                executable.execute();
//                BaseTestCase.result.writeInFile(3, Integer.parseInt(key), "pass", false);
            } catch (Throwable t) {
                UnrecoverableExceptions.rethrowIfUnrecoverable(t);
//                BaseTestCase.result.writeInFile(5, Integer.parseInt(key), t.getMessage(), true);
//                BaseTestCase.result.writeInFile(3, Integer.parseInt(key), "fail", true);
                failures.add(t);
            }
        }

        try {
            if (!failures.isEmpty()) {
                MultipleFailuresError multipleFailuresError = new MultipleFailuresError(heading, failures);
                failures.forEach(multipleFailuresError::addSuppressed);
                throw multipleFailuresError;
            }

        } finally {
            jsonAssertions = new JSONObject();
        }
    }
}
